#include "gpio.hpp"

using namespace device;

uint16_t *mGpioOutPartition[] = {(uint16_t *)&M4_PORT->PODRA, (uint16_t *)&M4_PORT->PODRB, (uint16_t *)&M4_PORT->PODRC, (uint16_t *)&M4_PORT->PODRD, (uint16_t *)&M4_PORT->PODRE, (uint16_t *)&M4_PORT->PODRH};
uint16_t *mGpioInPartition[] = {(uint16_t *)&M4_PORT->PIDRA , (uint16_t *)&M4_PORT->PIDRB, (uint16_t *)&M4_PORT->PIDRC, (uint16_t *)&M4_PORT->PIDRD, (uint16_t *)&M4_PORT->PIDRE, (uint16_t *)&M4_PORT->PIDRH};

void gpio::Write(GpioPortTPDF tGpioPort, uint8_t ucPin, uint8_t ucStatus)
{	
	if(ucStatus)
	{
		*mGpioOutPartition[tGpioPort] |= 1 << ucPin;
	}
	else
	{
		*mGpioOutPartition[tGpioPort] &= ~(1 << ucPin);
	}
}

void gpio::Modify(GpioPortTPDF tGpioPort, uint32_t uiMask, uint32_t uiData)
{
	*mGpioOutPartition[tGpioPort] = (*mGpioOutPartition[tGpioPort] & uiMask) | uiData;
}

void gpio::Toggle(GpioPortTPDF tGpioPort, uint8_t ucPin)
{
	if(*mGpioOutPartition[tGpioPort] & (1 << ucPin))
	{
		*mGpioOutPartition[tGpioPort] &= ~(1 << ucPin);
	}
	else
	{
		*mGpioOutPartition[tGpioPort] |= 1 << ucPin;
	}
}

uint8_t gpio::Read(GpioPortTPDF tGpioPort, uint8_t ucPin)
{
	return(*mGpioInPartition[tGpioPort] & (1 << ucPin) ? 1: 0);
}

uint32_t gpio::Read(GpioPortTPDF tGpioPort)
{
	return((uint32_t)*mGpioInPartition[tGpioPort]);
}

void gpio::SetOutputMode(GpioPortTPDF tGpioPort, uint8_t ucPin, bool bPushPull)
{
	uint32_t *pcr = (uint32_t *)(((uint32_t)&M4_PORT->PCRA0) + (tGpioPort * 64) + (ucPin * 4));
	uint32_t *pfsr = (uint32_t *)(((uint32_t)&M4_PORT->PFSRA0) + (tGpioPort * 64) + (ucPin * 4));
	
	M4_PORT->PWPR = 0xA501u;
	*pcr = (3 << 4) | (bPushPull? 0: (1 << 2)) | (1 << 1);
	*pfsr = 0;
	M4_PORT->PWPR = 0xA500u;
}

void gpio::SetInputMode(GpioPortTPDF tGpioPort, uint8_t ucPin, bool bPullUp, bool bPullDown)
{
	uint32_t *pcr = (uint32_t *)(((uint32_t)&M4_PORT->PCRA0) + (tGpioPort * 64) + (ucPin * 4));
	uint32_t *pfsr = (uint32_t *)(((uint32_t)&M4_PORT->PFSRA0) + (tGpioPort * 64) + (ucPin * 4));
	
	M4_PORT->PWPR = 0xA501u;
	*pcr = (bPullUp? (1 << 6): 0) | (3 << 4);
	*pfsr = 0;
	M4_PORT->PWPR = 0xA500u;
}
